home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / System / Swatch / Development / swatch 1.7 / Support / pstring.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-28  |  10.6 KB  |  449 lines  |  [TEXT/KAHL]

  1. /**
  2.  
  3.     pstring.c
  4.     Copyright (c) 1989-1992, joe holt
  5.  
  6.  **/
  7.  
  8.  
  9. /**-----------------------------------------------------------------------------
  10.  **
  11.  ** Headers
  12.  **
  13.  **/
  14.  
  15. #ifndef __ctypes__
  16. #include "ctypes.h"
  17. #endif
  18.  
  19. #ifndef __pstring__
  20. #include "pstring.h"
  21. #endif
  22.  
  23.  
  24. /**-----------------------------------------------------------------------------
  25.  **
  26.  ** Private Variables
  27.  **
  28.  **/
  29.  
  30. static unsigned char upper_case_Mac_encoding[] = {
  31.  
  32. 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
  33. 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
  34. 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
  35. 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
  36. 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
  37. 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
  38. 0x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
  39. 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x7B,0x7C,0x7D,0x7E,0x7F,
  40.  
  41. 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0xCB,0x89,0x80,0xCC,0x81,0x82,0x83,0x8F,
  42. 0x90,0x91,0x92,0x93,0x94,0x95,0x84,0x97,0x98,0x99,0x85,0xCD,0x9C,0x9D,0x9E,0x86,
  43. 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
  44. 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xAE,0xAF,
  45. 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCE,
  46. 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
  47. 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
  48. 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
  49.  
  50. };
  51.  
  52.  
  53. /*******************************************************************************
  54.  **
  55.  **    Public Functions
  56.  **
  57.  **/
  58.  
  59. /*******************************************************************************
  60.  ***
  61.  *** unsigned char *pstrcopy( unsigned char *s1, unsigned char *s2 );
  62.  ***
  63.  *** Copy Pascal string <s1> to <s2>.
  64.  ***
  65.  *** Returns the address one byte past the end of new string <s2>.
  66.  ***
  67.  *** History:
  68.  ***   jhh 25 jul 89 -- template project; joe holt
  69.  ***
  70.  ***/
  71.  
  72. unsigned char *pstrcopy( unsigned char *s1, unsigned char *s2 )
  73. {
  74.     s2[0] = 0;
  75.     return pstrappend( s1, s2 );
  76. }
  77.  
  78.  
  79. /*******************************************************************************
  80.  ***
  81.  *** unsigned char *pstrappend( unsigned char *s1, unsigned char *s2 );
  82.  ***
  83.  *** Append Pascal string <s1> to <s2>.
  84.  ***
  85.  *** Returns the address one byte past the end of new string <s2>.
  86.  ***
  87.  *** History:
  88.  ***   jhh 25 jul 89 -- template project; joe holt
  89.  ***   jhh  9 dec 89 -- check for destination string overflow
  90.  ***
  91.  ***/
  92.  
  93. unsigned char *pstrappend( unsigned char *s1, unsigned char *s2 )
  94. {
  95.     asm {
  96.             movea.l    s1, A0
  97.             movea.l    s2, A1
  98.             moveq    #0, D0
  99.             moveq    #0, D1
  100.             move.b    (A0)+, D0
  101.             move.b    (A1), D1
  102.             add.b    D0, (A1)+            ; update length byte of s2
  103.             bcc.s    @1                    ; no overflow
  104.  
  105.             addq.b    #1, -(A1)            ; len(s1) + len(s2) > 255...
  106.             sub.b    (A1), D0            ; so append only as much as will fit
  107.             move.b    #255, (A1)+
  108. @1:            adda.w    D1, A1                ; begin adding s1 to old end of s2
  109.             bra.s    @3
  110.  
  111. @2:            move.b    (A0)+, (A1)+
  112. @3:            dbra    D0, @2
  113.  
  114.             move.l    A1, D0                ; return new end of s2
  115.     }
  116. }
  117.  
  118.  
  119. /*******************************************************************************
  120.  ***
  121.  *** unsigned char *pchappend( unsigned char ch, unsigned char *s2 );
  122.  ***
  123.  *** Append character <ch> to Pascal string <s2>.
  124.  ***
  125.  *** Returns the address one byte past the end of new string <s2>.
  126.  ***
  127.  *** History:
  128.  ***   jhh  9 dec 89 -- template project; joe holt
  129.  ***
  130.  ***/
  131.  
  132. unsigned char *pchappend( unsigned char ch, unsigned char *s2 )
  133. {
  134.     s2[pstrlen(s2)+1 ] = ch;
  135.     ++s2[0];
  136.     return &s2[pstrlen(s2)+1];
  137. }
  138.  
  139.  
  140. /*******************************************************************************
  141.  ***
  142.  *** unsigned char *pchcopy( unsigned char ch, unsigned char *s2 );
  143.  ***
  144.  *** Copy character <ch> to Pascal string <s2>.
  145.  ***
  146.  *** Returns the address one byte past the end of new string <s2>.
  147.  ***
  148.  *** History:
  149.  ***   jhh  9 dec 89 -- template project; joe holt
  150.  ***
  151.  ***/
  152.  
  153. unsigned char *pchcopy( unsigned char ch, unsigned char *s2 )
  154. {
  155.     s2[0] = 1;
  156.     s2[1] = ch;
  157.     return &s2[2];
  158. }
  159.  
  160.  
  161. /*******************************************************************************
  162.  ***
  163.  *** unsigned char *pnumcopy( int32 n, unsigned char *s2 );
  164.  ***
  165.  *** Copy (convert) number <n> to Pascal string <s2>.
  166.  ***
  167.  *** Returns the address one byte past the end of new string <s2>.
  168.  ***
  169.  *** History:
  170.  ***   jhh    sep 89 -- template project; joe holt
  171.  ***
  172.  ***/
  173.  
  174. unsigned char *pnumcopy( int32 n, unsigned char *s2 )
  175. {
  176.     s2[0] = 0;
  177.     return pnumappend( n, s2 );
  178. }
  179.  
  180.  
  181. /*******************************************************************************
  182.  ***
  183.  *** unsigned char *pnumappend( int32 n, unsigned char *s2 );
  184.  ***
  185.  *** Append (convert and append) number <n> to Pascal string <s2>.
  186.  ***
  187.  *** Returns the address one byte past the end of new string <s2>.
  188.  ***
  189.  *** History:
  190.  ***   jhh    sep 89 -- template project; joe holt
  191.  ***
  192.  ***/
  193.  
  194. unsigned char *pnumappend( int32 n, unsigned char *s2 )
  195. {
  196.     unsigned char snum[20];
  197.  
  198.     asm {
  199.             movem.l    D3/A2, -(A7)
  200.             lea        snum, A0
  201.             movea.l    A0, A1
  202.             clr.b    (A0)+
  203.             lea        @div, A2            ; beginning of divisor table
  204.             moveq    #0, D3                ; haven't seen non-zero digit yet
  205.             move.l    n, D0
  206.             bpl.s    @1                    ; number is positive, so is fine
  207.  
  208.             move.b    #'-', D2            ; negative, so add '-' and fix number
  209.             neg.l    D0
  210.             bra.s    @5
  211.  
  212. @1:            move.l    (A2)+, D1
  213.             beq.s    @6                    ; end of divisor table, so we're done
  214.  
  215.             moveq    #0, D2
  216.             bra.s    @3
  217.  
  218. @2:            addq.w    #1, D2                ; subtract the base 10 divisor...
  219. @3:            sub.l    D1, D0                ; ...until we underflow
  220.             bcc.s    @2
  221.  
  222.             add.l    D1, D0
  223.             tst.w    D2                    ; is this digit a zero?
  224.             bne.s    @4                    ; no, add into string
  225.  
  226.             cmpi.w    #1, D1                ; is it the "ones" digit?
  227.             beq.s    @4                    ; yes, add whether zero or not
  228.  
  229.             tst.w    D3                    ; otherwise ignore leading zeros
  230.             beq.s    @1
  231.  
  232. @4:            add.b    #'0', D2            ; convert to ASCII
  233.             moveq    #1, D3
  234. @5:            move.b    D2, (A0)+            ; and stuff into string
  235.             addq.b    #1, (A1)            ; update Pascal string length
  236.             bra.s    @1
  237.  
  238. @div:        dc.l    1000000000, 100000000, 10000000, 1000000, 100000
  239.             dc.l    10000, 1000, 100, 10, 1, 0
  240.  
  241. @6:            movem.l    (A7)+, D3/A2
  242.     }
  243.  
  244.     return pstrappend( snum, s2 );
  245. }
  246.  
  247.  
  248. /*******************************************************************************
  249.  ***
  250.  *** unsigned char *phexcopy( uns32 n, int16 d, unsigned char *s2 );
  251.  ***
  252.  *** Copy (convert) number <n> to Pascal string <s2>, hexadecimal.
  253.  ***
  254.  *** Returns the address one byte past the end of new string <s2>.
  255.  ***
  256.  *** History:
  257.  ***   jhh 29 oct 90 -- swatch; joe holt
  258.  ***
  259.  ***/
  260.  
  261. unsigned char *phexcopy( uns32 n, int16 d, unsigned char *s2 )
  262. {
  263.     s2[0] = 0;
  264.     return phexappend( n, d, s2 );
  265. }
  266.  
  267.  
  268. /*******************************************************************************
  269.  ***
  270.  *** unsigned char *phexappend(uns32 n, int16 d, unsigned char *s2);
  271.  ***
  272.  *** Append (convert) number <n> to Pascal string <s2>, hexadecimal.
  273.  ***
  274.  *** Returns the address one byte past the end of new string <s2>.
  275.  ***
  276.  *** History:
  277.  ***   jhh 29 oct 90 -- swatch; joe holt
  278.  ***
  279.  ***/
  280.  
  281. unsigned char *phexappend( uns32 n, int16 d, unsigned char *s2 )
  282. {
  283.     asm {
  284.             movea.l    s2, A0                ; new length = length + d
  285.             movea.l    A0, A1
  286.             moveq    #0, D0
  287.             move.b    (A0)+, D0
  288.             add.w    D0, A0                ; point to end of string
  289.             add.w    d, D0
  290.             move.b    D0, (A1)
  291.  
  292. ;**
  293. ;
  294. ; Convert number to hexadecimal ASCII representation.  First, preshift number
  295. ; so that msdigit is in msbit.  For example, if <d> is 4, then convert the
  296. ; long xxxx1234 to 12340000.  From this point we roll the digits off the top
  297. ; and around into the lsbyte and convert.
  298. ;
  299. ; 23400001  -->  '1'    "1"
  300. ; 34000012  -->  '2'    "12"
  301. ; 40000123  -->  '3'    "123"
  302. ; 00001234  -->  '4'    "1234"
  303. ;
  304. ; **
  305.  
  306.             move.l    n, D2                ; preshift
  307.             move.w    d, D0
  308.             moveq    #8, D1
  309.             sub.w    D0, D1
  310.             beq.s    @4
  311.  
  312.             add.w    D1, D1
  313.             add.w    D1, D1
  314.             lsl.l    D1, D2
  315.             bra.s    @4
  316.  
  317. @1:            rol.l    #4, D2                ; get next digit
  318.             move.b    D2, D1
  319.             andi.b    #0x0F, D1
  320.             cmpi.b    #10, D1
  321.             blt.s    @2
  322.  
  323.             addi.b    #'A'-10, D1            ; convert 10-15 to 'A'-'F'
  324.             bra.s    @3
  325.  
  326. @2:            addi.b    #'0', D1            ; or convert 0-9 to '0'-'9'
  327. @3:            move.b    D1, (A0)+
  328. @4:            dbra    D0, @1
  329.  
  330.             move.l    A0, D0
  331.     }
  332. }
  333.  
  334.  
  335. /*******************************************************************************
  336.  ***
  337.  *** Boolean pstrequal( unsigned char *s1, unsigned char *s2 )
  338.  ***
  339.  *** Compare Pascal string <s1> to <s2>.  Returns true if the strings are equal.
  340.  *** The compare is case-insensitive but diacritical-sensitive.
  341.  ***
  342.  *** History:
  343.  ***   jhh 24 jul 89 -- template project; joe holt
  344.  ***   jhh    nov 89 -- added case insensitivity
  345.  ***   jhh 14 dec 89 -- changed to use Macintosh case translations; see function
  346.  ***                    chtoupper()
  347.  ***
  348.  ***/
  349.  
  350. Boolean pstrequal( unsigned char *s1, unsigned char *s2 )
  351. {
  352.     asm {
  353.             move.l    A2, -(A7)
  354.             lea        upper_case_Mac_encoding, A2
  355.             moveq    #0, D0
  356.             moveq    #0, D1
  357.             move.l    s1, A0
  358.             move.l    s2, A1
  359.  
  360.             move.b    (A0)+, D1
  361.             cmp.b    (A1)+, D1
  362.             bra.s    @2
  363.             
  364. @1:            move.b    (A0)+, D0
  365.             move.b    (A2, D0.w), D2
  366.  
  367.             move.b    (A1)+, D0
  368.             cmp.b    (A2, D0.w), D2
  369. @2:            dbne    D1, @1
  370.  
  371.             seq.b    D0
  372.             and.b    #1, D0
  373.             move.l    (A7)+, A2
  374.     }
  375. }
  376.  
  377.  
  378. /*******************************************************************************
  379.  ***
  380.  *** unsigned char chtoupper( unsigned char ch )
  381.  ***
  382.  *** Convert character <ch> to upper case.  Uses case translation table which is
  383.  *** specific to Macintosh in the upper 128-character codes.  See the table in
  384.  *** _Inside AppleTalk_, Appendix D.
  385.  ***
  386.  *** History:
  387.  ***   jhh 14 dec 89 -- template project; joe holt
  388.  ***
  389.  ***/
  390.  
  391. unsigned char chtoupper( unsigned char ch )
  392. {
  393.     asm {
  394.             moveq    #0, D0
  395.             move.b    ch, D0
  396.             lea        upper_case_Mac_encoding, A0
  397.             move.b    (A0, D0.w), D0
  398.     }
  399. }
  400.  
  401.  
  402. /*******************************************************************************
  403.  ***
  404.  *** void blockzero( unsigned char *p1, int32 len );
  405.  ***
  406.  *** A very simple block clear function.
  407.  ***
  408.  *** History:
  409.  ***   jhh 24 jul 89 -- template project; joe holt
  410.  ***   jhh 10 dec 89 -- added odd-byte logic, now that the data structures are
  411.  ***                    packed tight.
  412.  ***   jhh 27 dec 89 -- added zero-length test; improved odd-byte logic.
  413.  ***
  414.  ***/
  415.  
  416. void blockzero( unsigned char *p1, int32 len )
  417. {
  418.     asm {
  419.             move.l    len, D0
  420.             beq.s    @5
  421.  
  422.             move.l    p1, D1
  423.             btst.l    #0, D1                ; is the destination address odd?
  424.             movea.l    D1, A0
  425.             beq.s    @0                    ; no, begin clearing away
  426.  
  427.             clr.b    (A0)+                ; yes, clear this one odd byte
  428.             subq.l    #1, D0
  429.             bmi.s    @5                    ; if that's it, then we're done
  430.  
  431. @0:            moveq    #0, D1                ; set up to clear by longs
  432.             bra.s    @2
  433.  
  434. @1:            move.l    D1, (A0)+
  435.             move.l    D1, (A0)+
  436. @2:            subq.l    #8, D0
  437.             bpl.s    @1
  438.  
  439.             addq.l    #8, D0
  440.             bra.s    @4
  441.  
  442. @3:            clr.b    (A0)+                ; clear the rest by bytes
  443. @4:            subq.l    #1, D0
  444.             bpl.s    @3
  445.  
  446. @5:
  447.     }
  448. }
  449.